/*
* License:  This  program  is  free  software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the  Free Software Foundation; either version 3 of the License, or (at your
* option)  any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*/

package pcgen.CharacterViewer.fragments;

import java.io.File;
import java.net.URLDecoder;

import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

import de.hilses.droidreader.DroidReaderDocument;
import de.hilses.droidreader.DroidReaderFontProvider;
import de.hilses.droidreader.DroidReaderView;
import de.hilses.droidreader.PageLoadException;
import de.hilses.droidreader.PasswordNeededException;
import de.hilses.droidreader.PdfRender;
import de.hilses.droidreader.WrongPasswordException;

import pcgen.CharacterViewer.R;

public class DroidReaderContentFragment extends AppTabContentFragment
{
	private static final int DIALOG_GET_PASSWORD = 1;
    
	private String _location;
	private DroidReaderDocument _document;
	private DroidReaderView _viewer;

    private String _filename;
    private String _password;

    private int _pageNo;

    private boolean _documentIsOpen = false;
    private boolean _loadedDocument = false;
	
	public DroidReaderContentFragment(String name)
	{
		super(name);
	}

	public void onCreate(Bundle savedInstanceState)
	{
	    if (_document == null)
	    	_document = new DroidReaderDocument();
	    
	    // Initialize the PdfRender engine
        PdfRender.setFontProvider(new DroidReaderFontProvider(getActivity()));

        _viewer = new DroidReaderView(getActivity(), null, _document);
        
        readPreferences();

        // The priority for loading files is:
        // 1) Check the bundle for a saved instance. If there is one, then
        // reload it. This has to be before the check for an intent because
        // the intent that was used when the app was first opened is
        // supplied again after an instance cycle such as happens when
        // you rotate the screen. This means that if another PDF was
        // opened after the app was started, and then the screen is rotated,
        // the app will go back to the original document if the intent is
        // given first priority.
        // 2) Check for an intent that indicates the app was started by
        // selecting a PDF in a file manager etc.
        // 3) Check what document was open last time the app closed down, and
        // re-open it.
        if (savedInstanceState != null) {
            _filename = savedInstanceState.getString("filename");
            if((new File(_filename)).exists()) {
                _password = savedInstanceState.getString("password");
                _document.mZoom = savedInstanceState.getFloat("zoom");
                _document.mRotation = savedInstanceState.getInt("rotation");
                _pageNo = savedInstanceState.getInt("page");
//                mOffsetX = savedInstanceState.getInt("offsetX");
//                mOffsetY = savedInstanceState.getInt("offsetY");
                _document.mMarginOffsetX = savedInstanceState.getInt("marginOffsetX");
                _document.mMarginOffsetY = savedInstanceState.getInt("marginOffsetY");
                _document.mContentFitMode = savedInstanceState.getInt("contentFitMode");
                openDocument();
                _loadedDocument = true;
            }
            savedInstanceState.clear();
        }

        if (!_loadedDocument) {
            // No filename supplied and no saved instance state. Re-open the last document
            // that was viewed, if there was one.
            tryLoadLastFile();
        }
	}

    @Override
    public void onDestroy() {
        if (_document != null)
        	_document.closeDocument();
        super.onDestroy();
    }

    @Override
    public void onPause() {
        super.onPause();
        // Store the name of the document being viewed, so it can be re-called
        // next time if the app is started without a filename.
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        prefs.edit().putString("last_open_file", _filename).commit();

        // Also store the view details for this document in the database so the
        // view can be restored.
        //readOrWriteDB(true);
    }
	
	@Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if((_document != null) && _document.isPageLoaded()) {
            outState.putFloat("zoom", _document.mZoom);
            outState.putInt("rotation", _document.mRotation);
            outState.putInt("page", _document.mPage.no);
            outState.putInt("offsetX", _document.mOffsetX);
            outState.putInt("offsetY", _document.mOffsetY);
            outState.putInt("marginOffsetX", _document.mMarginOffsetX);
            outState.putInt("marginOffsetY", _document.mMarginOffsetY);
            outState.putInt("contentFitMode", _document.mContentFitMode);
            outState.putString("password", _password);
            outState.putString("filename", _filename);
            _document.closeDocument();
        }
    }
	
	@Override
	public int getLayoutId() 
	{
		return R.layout.tab_content_web;
	}

	@Override
	public void onSelected() 
    {
		loadContent();
    }

    @Override
	public void onUnselected() 
    {
    	//_view.clearView();
    }

    @Override
	public void onReselected() 
    {
		loadContent();
    }
	
	public void setLocation(String location)
	{
		_location = location;
		loadContent();
	}

    protected void tryLoadLastFile() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        _filename = prefs.getString("last_open_file","");
        if (_filename != null) {
            if ((_filename.length() > 0) && ((new File(_filename)).exists())) {
                // Don't URL-decode the filename, as that's presumably
                // already been done.
                _password="";
                openDocumentWithLookup();
                _loadedDocument = true;
            }
        }
    }

    // URL-decode the filename, look it up in the database of previous
    // views, and then open the document.
    protected void openDocumentWithDecodeAndLookup(String fileName) {
        try {
            // File names are URL-encoded (i.e. special chars are replaced
            // with %-escaped numbers). Decode them before opening.
            String temporaryFilename = URLDecoder.decode(fileName,"utf-8");

            // Do some sanity checks on the supplied filename.
            File f=new File(temporaryFilename);

            if ((f.exists()) && (f.isFile()) && (f.canRead())) {
                _filename = temporaryFilename;
                openDocumentWithLookup();
            } else {
                Toast.makeText(getActivity(), R.string.error_file_open_failed,
                        Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {
            Toast.makeText(getActivity(), R.string.error_opening_document,
                    Toast.LENGTH_LONG).show();
        }
    }

    protected void openDocumentWithLookup() {
        //readOrWriteDB(false);
        openDocument();
    }

    protected void openDocument() {
        // Store the view details for the previous document and close it.
        if (_documentIsOpen) {
            _document.closeDocument();
            _documentIsOpen = false;
        }
        try {
            //this.setTitle(_filename);
            _document.open(_filename, _password, _pageNo);
            openPage(0, true);
            _documentIsOpen = true;
        } catch (PasswordNeededException e) {
            //showDialog(DIALOG_GET_PASSWORD);
        } catch (WrongPasswordException e) {
            Toast.makeText(getActivity(), R.string.error_wrong_password,
                    Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            Toast.makeText(getActivity(), R.string.error_opening_document,
                    Toast.LENGTH_LONG).show();
        }
    }

    protected void openPage(int no, boolean isRelative) {
        try {
            if(!(no == 0 && isRelative))
                _document.openPage(no, isRelative);
            //this.setTitle(new File(_filename).getName()+String.format(" (%d/%d)",_document.mPage.no,_document._document.pagecount));
            _pageNo = _document.mPage.no;
        } catch (PageLoadException e) {
            // TODO Auto-generated catch block
        }
    }

    protected void setZoom(float newZoom) {
        newZoom = newZoom / (float)100.0;
        if (newZoom > 16.0)
            newZoom = (float)16.0;
        if (newZoom < 0.0625)
            newZoom = (float)0.0625;
        _document.setZoom(newZoom, false);
    }

    private void readPreferences() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        DisplayMetrics metrics = new DisplayMetrics();
        this.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);

        if(prefs.getString("zoom_type", "0").equals("0")) {
            float zoom = Float.parseFloat(prefs.getString("zoom_percent", "50"));
            if((1 <= zoom) && (1000 >= zoom)) {
                _document.setZoom(zoom / 100, false);
            }
        } else {
            _document.setZoom(Float.parseFloat(prefs.getString("zoom_type", "0")), false);
        }

        if(prefs.getBoolean("dpi_auto", true)) {
            // read the display's DPI
            _document.setDpi((int) metrics.xdpi, (int) metrics.ydpi);
        } else {
            int dpi = Integer.parseInt(prefs.getString("dpi_manual", "160"));
            if((dpi < 1) || (dpi > 4096))
                dpi = 160; // sanity check fallback
            _document.setDpi(dpi, dpi);
        }

        if(prefs.getBoolean("tilesize_by_factor", true)) {
            // set the tile size for rendering by factor
            Float factor = Float.parseFloat(prefs.getString("tilesize_factor", "1.5"));
            _document.setTileMax((int) (metrics.widthPixels * factor), (int) (metrics.heightPixels * factor));
        } else {
            int tilesize_x = Integer.parseInt(prefs.getString("tilesize_x", "640"));
            int tilesize_y = Integer.parseInt(prefs.getString("tilesize_x", "480"));
            if(metrics.widthPixels < metrics.heightPixels) {
                _document.setTileMax(tilesize_x, tilesize_y);
            } else {
                _document.setTileMax(tilesize_y, tilesize_x);
            }
        }

        boolean invert = prefs.getBoolean("invert_display", false);
        _document.setDisplayInvert(invert);
        _viewer.setDisplayInvert(invert);

        if (prefs.getBoolean("full_screen",false)) {
            this.getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        } else {
            this.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }

        _document.mHorizontalScrollLock = prefs.getBoolean("horizontal_scroll_lock",false);
    }
	
	protected void loadContent()
	{
		//if (_view != null)
		//	_view.loadData(_location, "text/html", "UTF-8");
	}
	
	@Override
	protected void inflateView(View view)
	{
		//_view = (WebView)view.findViewById(R.id.webView1);
		//_view.getSettings().setJavaScriptEnabled(true);
		loadContent();
	}
	
	public void readOrWriteDB(boolean doWrite) 
	{
        SQLiteDatabase pdfDB = null;
        try 
        {
            pdfDB = getActivity().openOrCreateDatabase("CharacterViewerDB", Context.MODE_PRIVATE, null );
            Cursor c = pdfDB.rawQuery ("SELECT * FROM LastReadPoint WHERE Filename = '" + _filename + "'", null);

            // c shouldn't be null, if it is then there's an external problem
            if (c != null) {
                if (c.getCount() > 0) {
                    // There's already an entry for this file.
                    c.moveToFirst();
                    if (doWrite) {
                        pdfDB.execSQL("UPDATE LastReadPoint SET " +
                            "Zoom = " + _document.mZoom + " , " +
                            "Rotation = " + _document.mRotation + " , " +
                            "Page = " + _pageNo + " , " +
                            "OffsetX = " + _document.mOffsetX + " , " +
                            "OffsetY = " + _document.mOffsetY + " , " +
                            "MarginOffsetX = " + _document.mMarginOffsetX + " , " +
                            "MarginOffsetY = " + _document.mMarginOffsetY + " , " +
                            "ContentFitMode = " + _document.mContentFitMode + " , MemoryMode = 0 ," +
                            "Password = '" + _password + "' " +
                            "WHERE Filename = '" + _filename + "';");
                    } else {
                        _document.mZoom = c.getFloat(c.getColumnIndex("Zoom"));
                        _document.mRotation = c.getInt(c.getColumnIndex("Rotation"));
                        _pageNo = c.getInt(c.getColumnIndex("Page"));
                        if (_pageNo == 0)
                        	_pageNo = 1;
//                        mOffsetX = c.getInt(c.getColumnIndex("OffsetX"));
//                        mOffsetY = c.getInt(c.getColumnIndex("OffsetY"));
                        _document.mMarginOffsetX = c.getInt(c.getColumnIndex("MarginOffsetX"));
                        _document.mMarginOffsetY = c.getInt(c.getColumnIndex("MarginOffsetY"));
                        _document.mContentFitMode = c.getInt(c.getColumnIndex("ContentFitMode"));

// Don't restore the password. This would be a bit of a security nightmare,
// because documents would be unsecured after the password was entered once -
// and there wouldn't be any way to re-secure them. Presumably people who
// use password-protected PDFs will prefer to enter the password whenever they
// open the document.
//						if (mPassword.length() == 0) {
//							mPassword = c.getString(c.getColumnIndex("Password"));
//						}
                    }
                } else {
                    // No entry found for this file.
                    if (doWrite) {
                        pdfDB.execSQL("INSERT INTO LastReadPoint VALUES ('" +
                            _filename + "', " +
                            _document.mZoom + " , " +
                            _document.mRotation + " , " +
                            _pageNo + " , " +
                            _document.mOffsetX + " , " +
                            _document.mOffsetY + " , " +
                            _document.mMarginOffsetX + " , " +
                            _document.mMarginOffsetY + " , " +
                            _document.mContentFitMode + " , 0 , '" +
                            _password + "');" );
                    } else {
                        // reading: Set some default values
                        _document.mZoom = DroidReaderDocument.ZOOM_FIT;
                        _document.mRotation = 0;
//                        mOffsetX = 0;
//                        mOffsetY = 0;
                        _document.mMarginOffsetX = 0;
                        _document.mMarginOffsetY = 0;
                        _document.mContentFitMode = 0;
                        _pageNo = 1;
                    }
                }
                c.close();
            } else {
                Log.d (getClass().getSimpleName(), "Problem here... no Cursor, query must have failed");
            }
        } catch (SQLiteException se ) {
            Log.e(getClass().getSimpleName(), "Could not create or open the database");
        } finally {
            if (pdfDB != null) {
                pdfDB.close();
            }
        }
    }
}
